﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWMAG.Scripting.Helpers;
using IWMAG.Scripting.AST.ObjectModel;
using IWMAG.Scripting.Types;
using IWMAG.Scripting.AST.Statements;
using System.Reflection;

namespace IWMAG.Scripting.AST.Declarations {
    public class ProgramDeclaration : CodeDeclaration {
        public List<FunctionDeclaration> Functions = new List<FunctionDeclaration>();
        public List<VariableDeclaration> Variables = new List<VariableDeclaration>();
        public List<ImportStatement> Imports = new List<ImportStatement>();
        public List<AliasStatement> Aliases = new List<AliasStatement>();
        public List<ExternDeclaration> Externs = new List<ExternDeclaration>();

        public ProgramDeclaration() : base(default(Compiler.Lexeme)) {

        }

        public static implicit operator CompileTable(ProgramDeclaration prog){
            CompileTable ret = new CompileTable();
            foreach (VariableDeclaration var in prog.Variables) {
                ret.Variables[var.Name] = var.Type;
            }

            foreach (FunctionDeclaration f in prog.Functions) {
                ret.Functions[f.Signature.Name] = f.Signature;
            }

            foreach (ImportStatement imp in prog.Imports) {
                ret.Imports[(ReferenceType)imp.ClrName] = imp.ClrType;
                if (imp.Alias != null) {
                    ret.Aliases[(ReferenceType) imp.Alias] = imp.ClrName;
                }
            }

            foreach (AliasStatement al in prog.Aliases) {
                ret.Aliases[(ReferenceType)al.Alias] = al.Type;
            }

            foreach (ExternDeclaration ext in prog.Externs) {
                ret.Functions[ext.Signature.Name] = ext.Signature;
            }
            
            return ret;
        }

        public static implicit operator RuntimeTable(ProgramDeclaration prog) {
            RuntimeTable ret = new RuntimeTable(prog);
            foreach (FunctionDeclaration f in prog.Functions) {
                ret.Functions[f.Signature.Name] = f;
            }

            ret.Program = prog;

            return ret;
        }

        public override void Verify(Helpers.CompileTable sym, List<Compiler.IUserInfo> error) {
            foreach (VariableDeclaration var in Variables) {
                var.Verify(sym, error);
            }

            foreach (FunctionDeclaration func in Functions) {
                func.Verify(sym, error);
            }

            foreach (AliasStatement alias in Aliases) {
                alias.Verify(sym, error);
            }
        }
    }
}
